home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 147
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin
/
tools
/
zmc3v078
/
zmc3v078.lzh
/
SRCSV078.LZH
/
ZMC3.C
< prev
next >
Wrap
C/C++ Source or Header
|
2000-06-09
|
16KB
|
616 lines
/* ======================================
ZMC3.{X,EXE} ... ZMS->ZMD compiler
for non X680x0 architectures
====================================== */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "config.h"
#ifndef UNIXY_OS /* for setmode() */
#include <fcntl.h>
#include <io.h>
#ifdef X68000
#include <unistd.h>
#endif
#endif
#include "switch.h"
#include "readfile.h"
#include "makezmd.h"
#include "etc.h"
void help(int exitcode,int helpmode);
FILE *openOutFile(void);
void writeZmdFile(TRKCHINF *trkdata, COMMONINF *cominf, DWORD totalstep);
void checkSwitch(void);
UBYTE *makeZmdHeaderBlock(TRKCHINF *trkdata,COMMONINF *cominf, DWORD totalstep);
UBYTE *makeTrkChInfoTable(TRKCHINF *trkdata,COMMONINF *cominf, UDWORD *bytes);
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#define TOTALHEAD 80 /* header size */
int main(int argc,char *argv[])
{
UBYTE *zmsbuf;
TRKCHINF *trkdata;
COMMONINF cominf;
int i;
DWORD totalstep = 0;
#ifdef UNIXY_OS
const char *inpEXT[] = { ".zms", ".zm3", ".opm", NULL};
const char *outEXT = ".zmd";
#else
const char *inpEXT[] = { ".ZMS", ".ZM3", ".OPM", NULL};
const char *outEXT = ".ZMD";
#endif
srand(time(NULL));
i = getSwitch(argc,argv); /* get switches/sourcefilename/dest.file */
/* setvbuf(stderr,NULL,_IONBF,0); */ /* no output buffering */
fprintf(stderr,"ZMS to ZMD(V3) compiler version 0.78, by Mamiya / Y.Yagi,\n");
fprintf(stderr,"from Z-MUSIC UNIVERSAL VERSION 3.01A (C) ZENJI SOFT\n");
if (i) { /* bootup without any arguments */
help(0,0);
}
checkSwitch();
if (!getInFile()[0]) {
#ifdef UNIXY_OS
setInFile("-");
#else
fatal(FILENOTFOUND,"Error: source file is not specified.\n");
#endif
}
zmsbuf = readFile(getInFile(),getOutFile(),inpEXT,outEXT);
trkdata = makeZmd(zmsbuf,getInFile(),&cominf, &totalstep);
writeZmdFile(trkdata,&cominf, totalstep);
/* free(zmsbuf); */ /* already free-ed in v3macro.c */
#ifdef MEMDEBUG
/* memdebug();
*/
#endif
return EXIT_SUCCESS;
}
/* =======================================================
open output file (with dispatching FILE and STDOUT)
======================================================= */
FILE *openOutFile(void)
{
int stdoutflg = 0;
FILE *fp;
if (getSwitchVal('c') != RES_VAL) { /* use stdout */
stdoutflg = 1;
}
if (stdoutflg) {
#ifndef UNIXY_OS /* set stdin to binary mode (MS-DOS only) */
#if defined (X68000) || defined (BCB)
#ifndef XCLIB
setmode(fileno(stdout),O_BINARY); /* for BCB, DOS, OS/2, X680x0(libc) */
#else
fmode(stdout, _IOBINARY); /* for X68000(XC) */
#endif
#elif defined (__TURBOC__)
setmode((stdout)->fd,O_BINARY); /* for DOS(TurboC) */
#elif defined (TOWNS)
_setmode(stdout, _BINARY); /* for TOWNS(HIGH-C) */
#endif
#endif /* UNIXY_OS */
fp = stdout;
} else {
fp = fopen(getOutFile(),"wb");
if (fp == (FILE*)NULL) {
fatal(1,"%s\tError: destination file can't open.",getOutFile());
}
}
return fp;
}
/* =======================
write all ZMD files
======================= */
void writeZmdFile(TRKCHINF *trkdata, COMMONINF *cominf, DWORD totalstep)
{
int trks = 0, i, firsttrk = 1;
FILE *fp;
UDWORD bytes, bytes2;
DWORD offset;
UBYTE tmp[16];
int stdoutflg = 0;
UBYTE *headdata, *trktbl;
fp = openOutFile();
if (fp == stdout) {
stdoutflg = 1;
}
/* header block */
headdata = makeZmdHeaderBlock(trkdata, cominf, totalstep);
bytes = fwrite(headdata, sizeof(UBYTE), TOTALHEAD, fp);
if (!stdoutflg && bytes < TOTALHEAD) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
efree(headdata,"headdata");
/* common track */
if (trkdata[0].nowsize) {
/* if ther is a common track */
bytes = fwrite(trkdata[0].zmdbuf,sizeof(UBYTE),trkdata[0].nowsize,fp);
if (!stdoutflg && bytes < (UDWORD)trkdata[0].nowsize) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
}
efree(trkdata[0].zmdbuf,"zmdbuf");
/* trk/ch info.table */
trktbl = makeTrkChInfoTable(trkdata, cominf, &bytes2);
bytes = fwrite(trktbl, sizeof(UBYTE), bytes2, fp);
if (!stdoutflg && bytes < bytes2) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
efree(trktbl,"trktbl");
/* trk data / trk additional info */
#ifdef AAA
for (i = 1; cominf.trkassign[i] >= 0; i++) {
if (trkdata[Trk].mute && (*trkdata[Trk].zmdbuf != 0xFF || getSwitchVal('z') >= 3)) {
trks++;
}
}
/* printf("trks=%d\n",trks); */
putWordAlign(tmp,trks);
bytes = fwrite(tmp,sizeof(UBYTE),2,fp);
if (!stdoutflg && bytes < 2) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
offset = trks * 6 - 4;
/* hedder part2 */
for (i = 0; i < trks; i++) {
/* putDwordAlign(tmp,offset); */
putDword(tmp,offset);
*(tmp + 4) = 0;
*(tmp + 5) = trkdata[cominf.trkassign[i]].ch;
bytes = fwrite(tmp,sizeof(UBYTE),6,fp);
if (!stdoutflg && bytes < 6) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
offset += trkdata[cominf.trkassign[i]].nowsize;
offset -= 6;
}
/* data */
#endif
for (i = 0; cominf->trkassign[i] >= 0; i++) {
const int Trk = cominf->trkassign[i];
if ((trkdata[Trk].mute && *trkdata[Trk].zmdbuf != 0xFF) || getSwitchVal('z') >= 3) {
UDWORD len = 0;
if (firsttrk) { /* +2 padding for TRKS(word) */
int i;
for (i = 0; i < 2; i++) {
fputc(0x2F, fp);
}
firsttrk = 0;
}
putDword(tmp , 0); /* track total step time */
putDword(tmp + 4, 0); /* track checksum */
putDword(tmp + 8, 0); /* pars */
if (trkdata[Trk].cmnt) {
putDword(tmp + 12, strlen(trkdata[Trk].cmnt)); /* comment len */
} else {
putDword(tmp + 12, 0);
}
bytes = fwrite(tmp,sizeof(UBYTE),16,fp);
if (!stdoutflg && bytes < 16) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
if (trkdata[Trk].cmnt) {
len = strlen(trkdata[Trk].cmnt);
bytes = fwrite(trkdata[Trk].cmnt, sizeof(UBYTE),len, fp);
if (!stdoutflg && bytes < len) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
/* efree(trkdata[Trk].cmnt,"trkdata[Trk].cmnt"); */
}
if (len & 1) { /* padding if need */
fputc(0, fp);
}
#ifdef AA
if (len & 3) { /* padding if need */
int i;
for (i = (len & 3); i < 4; i++) {
fputc(0, fp);
}
}
#endif
bytes = fwrite(trkdata[Trk].zmdbuf,sizeof(UBYTE),
trkdata[Trk].nowsize,fp);
if (!stdoutflg && bytes < (UDWORD)trkdata[Trk].nowsize) {
fatal(1,"%s\tError: destination file can't write.",getOutFile());
}
#ifdef Aa
{
FILE *fp2;
char file[256];
sprintf(file,"%d.tmp",Trk);
fp2 = fopen(file,"wb");
fwrite(trkdata[Trk].zmdbuf,sizeof(UBYTE),
trkdata[Trk].nowsize,fp2);
fclose(fp2);
}
#endif
}
if (trkdata[Trk].cmnt) {
efree(trkdata[Trk].cmnt,"trkdata[Trk].cmnt");
}
efree(trkdata[Trk].zmdbuf, "trkdata[Trk].zmdbuf");
}
if (!stdoutflg) {
fclose(fp);
}
/*
efree(trktbl);
efree(headdata);
*/
efree(trkdata,"trkdata");
}
/* ================
put usage
================ */
void help(int exitcode,int helpmode)
{
const char *helpmes[] = {
#ifdef UNIXY_OS
"usage: zmc3 [-switches] source[.zms] [-o destination[.zmd]] [-e errfile]",
#else
"usage: zmc3 [-switches] source[.ZMS] [-o destination[.ZMD]] [-e errfile]",
#endif
#if WARNLVL == 1
"switch: -Wnum warning level(1=none(default), 2=as V2(traditional),",
" 3=as V3, 4=most strict)",
#elif WARNLVL == 2
"switch: -Wnum warning level(1=none, 2=as V2(traditional,default),",
" 3=as V3(default), 4=most strict)",
#elif WARNLVL == 3
"switch: -Wnum warning level(1=none, 2=as V2(traditional),",
" 3=as V3(default), 4=most strict)",
#else
"switch: -Wnum warning level(1=none, 2=as V2(traditional),",
" 3=as V3, 4=most strict(default))",
#endif
" -Znum compatible level(1=normal(default),",
" 3=ZMUSIC.X -c)",
" - use standard input (you must use it w/ -c or -o)",
" -c use standard output",
" -e errfile redirect stderr to specified file",
" -l change warning/error message pattern",
" -o destname specify ZMD filename",
" -h show this help messages",
"",
"Some FM/ADPCM MMLs will be ignored. (however to be supported)",
/* "FM/ADPCM MMLs will be ignored.", */
/*
"",
"If you want to show TIPS, type; zmc3 -h1 | more",
*/
NULL,
"zmc3 tips",
" When warning level is 1 or 2, zmc2-extended-MML will be warned.",
"e.g. YAMAHA-exclusive, portament MML at begining of line",
"",
"You can get the latest version at http://www2s.biglobe.ne.jp/~yyagi/",
NULL
};
char **str = (char**)helpmes;
if (helpmode) {
while (*str++ != NULL)
;
}
do {
fputs(*str++,stderr);
fputs("\n",stderr);
} while (*str != NULL);
exit(exitcode);
}
/* ==================
check switches
================== */
void checkSwitch()
{
int tmp;
tmp = getSwitchVal('h');
if (tmp == 1) {
help(0,1);
} else if (tmp != RES_VAL) {
help(0,0);
}
if (getOutFile()[0] && getSwitchVal('c') != RES_VAL) {
fatal(TOOMANYFILES,"You cannot use both -c and -o.\n");
}
if (getSwitchVal('w') == SET_VAL) {
fatal(SWERR,"You cannot omit -w's parameter.\n");
}
}
/* =========================================================
make ZMD header table
even if there are no common track and noplayng track,
this table is required.
========================================================= */
UBYTE *makeZmdHeaderBlock(TRKCHINF *trkdata,COMMONINF *cominf, DWORD totalstep)
{
UBYTE *head, *head_;
int i;
DWORD trks = 0;
DWORD totaltrksize = 2 + 2; /* 2(trks.w) and 2(padding) */
head_ = head = (UBYTE*)emalloc(sizeof(UBYTE) * TOTALHEAD, "headerBlock");
strcpy(head,"\x1aZmuSiC\x30"); /* Z-MUSIC ID */
head += 8;
if (trkdata[0].nowsize) { /* offset to CommonBlock */
putDword(head, TOTALHEAD - (head - head_) - 4);
} else {
putDword(head, 0);
}
head += 4;
/*
fprintf(stderr,"total=%d ",totaltrksize);
*/
for (i = 0; cominf->trkassign[i] >= 0; i++) {
const int Trk = cominf->trkassign[i];
if ((trkdata[Trk].mute && *trkdata[Trk].zmdbuf != 0xFF) || (getSwitchVal('z') >= 3) ) {
trks++;
totaltrksize += trkdata[Trk].nowsize;
/*
fprintf(stderr,"total=%d ",totaltrksize);
*/
/* playing trk */
totaltrksize += 16; /* size for trk/ch info. table */
totaltrksize += 16; /* trk additional info */
if (trkdata[Trk].cmnt) {
totaltrksize += strlen(trkdata[Trk].cmnt);
}
while (totaltrksize & 3) {
totaltrksize++;
}
}
}
#ifdef A
if (trkdata[0].zmdbuf[0] == 0xFF) { /* if there is no data in commontrk */
totaltrksize -= 2; /* delete 0xFF 0xFF */
}
#endif
/* fprintf(stderr,"trks=%x total=%x ",trks,totaltrksize); */
if (totaltrksize) { /* offset to trk/ch info. */
putDword(head, TOTALHEAD - (head - head_) - 4 + trkdata[0].nowsize);
} else {
putDword(head, 0);
}
/*
fprintf(stderr,"TOTALHEAD=%x, t0=%x, total=%x\n",TOTALHEAD,trkdata[0].nowsize, totaltrksize);
*/
/*========*/
head += 4;
putDword(head, 0); /* no support for playcommand */
head += 4;
putDword(head, TOTALHEAD + trkdata[0].nowsize + totaltrksize);
/* ZMD file size */
head += 4;
putDword(head, 0); /* no support for WRD data */
head += 4;
putDword(head, 0); /* reserved */
head += 4;
/*========*/
putDword(head, 0); /* total step time offset */
head += 4;
if (cominf->cmnt) { /* offset to the title */
putDword(head, TOTALHEAD - 0x28 + cominf->cmnt);
} else {
putDword(head, 0);
}
head += 4;
putDword(head, totalstep); /* total step time */
head += 4;
putDword(head, 0); /* playing time */
head += 4;
/*========*/
putWord(head, cominf->meter); /* meter n/m */
head += 2;
*head++ = 0; /* metronome speed */
*head++ = 0; /* reserved */
*head++ = cominf->key; /* key */
*head++ = cominf->majorflag; /* major / minor */
putWord(head, cominf->div); /* master clock */
head += 2;
putWord(head, cominf->tempo); /* tempo */
head += 2;
putWord(head, 0); /* reserved */
head += 2;
putDword(head, cominf->z_cmn_flag); /* com trk flag */
head += 4;
/*=========*/
putDword(head, 0); /* playcommand flag */
head += 4;
putDword(head, 0); /* the type of instruments */
head += 4;
*head++ = 0; /* #of FM ch */
*head++ = 0; /* #of ADPCM ch */
*head++ = trks; /* #of MIDI-1 ch *
*head++ = 0; /* #of MIDI-2 ch *
*head++ = 0; /* #of MIDI-3 ch *
*head++ = 0; /* reserved */
putWord(head, 0); /* reserved */
return head_;
}
UBYTE *makeTrkChInfoTable(TRKCHINF *trkdata,COMMONINF *cominf, UDWORD *bytes)
{
int i;
DWORD trks = 0, trk;
UBYTE *buf, *buf_;
DWORD headsize = 2;
DWORD trkofst;
int firsttrk = 1;
for (i = 0; cominf->trkassign[i] >= 0; i++) {
int Trk = cominf->trkassign[i];
if ((trkdata[Trk].mute && *trkdata[Trk].zmdbuf != 0xFF) || getSwitchVal('z') >= 3) {
trks++;
headsize += 16; /* size for trk/ch info. table */
}
}
/* *bytes = 2 + trks * 16; */
trkofst = headsize - 2 - 8 - 8; /* */
/*fprintf(stderr,"[size: %x]\n",headsize);*/
buf_ = buf = (UBYTE*)emalloc(sizeof(UBYTE) * headsize, "headerCommon");
putWord(buf, trks - 1);
buf += 2;
/* for (trk = 0; trk < trks; trk++) {*/
for (trk = 0; cominf->trkassign[trk] >= 0; trk++) {
int Trk = cominf->trkassign[trk];
if ((trkdata[Trk].mute && *trkdata[Trk].zmdbuf != 0xFF) || getSwitchVal('z') >= 3 ) {
*buf++ = 0; /* performance track */
if (trkdata[Trk].trkm) { /* track mode: normal/rhythm */
*buf++ = 0x80;
} else {
*buf++ = 0;
}
*buf++ = trkdata[Trk].trkf - 1; /* freq */
/* fprintf(stderr,"freq=%d ",trkdata[Trk].trkf - 1); */
*buf++ = 0; /* reserved */
putWord(buf, trkdata[Trk].chtype); /* channel */
/* fprintf(stderr,"chtype=%d ",trkdata[Trk].chtype); */
buf += 2;
putWord(buf, trkdata[Trk].ch_); /* channel */
/* fprintf(stderr,"ch=%d ",trkdata[Trk].ch_); */
buf += 2;
buf += 4; /* offset to track additional info. */
/* if (trk == 0) { */
if (firsttrk) {
trkofst += 2; /* +2 for trks[word] */
firsttrk = 0;
}
/*fprintf(stderr,"adinfo=%x ",trkofst);*/
putDword(buf, trkofst);
trkofst += 16;
if (trkdata[Trk].cmnt) {
trkofst += strlen(trkdata[Trk].cmnt);
/*fprintf(stderr,"(%d: %s)",Trk,trkdata[Trk].cmnt);*/
}
trkofst += 2;
while (trkofst & 1) {
trkofst++; /* padding if need */
}
#ifdef AA
if (trk == 0) { /* +2 for padding */
trkofst += 2;
}
#endif
/* trkofst += 2; */
trkofst += 2;
buf -= 4;
putDword(buf, trkofst); /* offset to track data */
/*fprintf(stderr,"trkofst=%.2x ",trkofst );*/
buf += 8;
trkofst += trkdata[Trk].nowsize;
/*
fprintf(stderr,"[trkofst=%.2x] ",trkofst);
*/
trkofst -= 16 + 4;
}
}
*bytes = headsize;
return buf_;
}
#ifdef AA
totaltrksize += trkdata[i].nowsize;
if (i) { /* playing trk */
totaltrksize += 18; /* size for trk/ch info. table */
if (trkdata[i].cmnt) {
totaltrksize += 16 + strlen(trkdata[i].cmnt);
}
}
#endif